package com.czy.ekp.module;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import com.czy.ekp.gen.GeneratorFactory;
import com.czy.ekp.gen.ModuleVo;
import com.czy.ekp.gen.TemplateCodeGenerator;
import com.czy.ekp.util.FileUtils;
import com.czy.ekp.util.ResultMap;
import com.wbs.rest.config.SqlRestContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@Service
public class ModuleService {

    final static String CHAR_SET = "UTF-8";


    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    SqlRestContext sqlRestContext;


    private Map<String, StringBuffer> createModuleFile(ModuleVo moduleVo) throws Exception{
        Map<String, StringBuffer> fileStrMap = new HashMap();
        for(String tempFile : GeneratorFactory.tempList){
            TemplateCodeGenerator generator = GeneratorFactory.newGenerator(tempFile);
            if(generator != null){
                generator.generate(moduleVo);
                fileStrMap.put(tempFile, generator.toBuffer());
            }else{
                log.error(tempFile + " has no generator.");
            }
        }
        return fileStrMap;
    }

    private Map<String, StringBuffer> createReportFile(ModuleVo moduleVo) throws Exception{
        Map<String, StringBuffer> fileStrMap = new HashMap();
        for(String tempFile : GeneratorFactory.tempList){
            TemplateCodeGenerator generator = GeneratorFactory.newGenerator(tempFile);
            if(generator != null){
                generator.generate(moduleVo);
                fileStrMap.put(tempFile, generator.toBuffer());
            }else{
                log.error(tempFile + " has no generator.");
            }
        }
        return fileStrMap;
    }


    /**
     * 生成模块
     * @param moduleVo
     * @return
     */
    public ResultMap generateModule(ModuleVo moduleVo, HttpServletResponse response){

        try{

            List<InputStream> isList = new ArrayList<>();

            for(StringBuffer buffer : createModuleFile(moduleVo).values()){
                isList.add(new ByteArrayInputStream(buffer.toString().getBytes(CHAR_SET)));
            }

            response.reset();
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(moduleVo.getModuleName()) + ".zip");
            FileUtils.zip(isList, GeneratorFactory.tempList, response.getOutputStream());

        }catch (Exception e){
            e.printStackTrace();
        }

        return ResultMap.success();
    }


    /**
     * 部署模块
     * @param file
     * @return
     */
    @Transactional
    public ResultMap deployModule(MultipartFile file){
        String deployPath = ResourceUtil.getResource("./").getFile() + "static/html";

        try{
            Map<String, OutputStream> osMap = new HashMap<>();
            for(String tempFile : GeneratorFactory.tempList){
                if(tempFile.endsWith(".html")){
                    File htmlFile = new File(deployPath + "/" + tempFile);
                    if(!htmlFile.exists()){
                        htmlFile.createNewFile();
                    }
                    osMap.put(tempFile, new FileOutputStream(htmlFile));
                }else if(tempFile.endsWith(".sql")){
                    osMap.put(tempFile, new ByteArrayOutputStream());
                }
            }

            FileUtils.unZip(file.getInputStream(), osMap);

            //处理sql
            StringBuilder sql = new StringBuilder();
            for(String tempFile : GeneratorFactory.tempList){
                if(tempFile.endsWith(".sql")){
                    ByteArrayOutputStream sqlOS = (ByteArrayOutputStream) osMap.get(tempFile);
                    sql.append(new String(sqlOS.toByteArray(), CHAR_SET));
                }
            }
            try{
                jdbcTemplate.execute(sql.toString());
                sqlRestContext.reloadMapping();
            }catch (Exception e){
                e.printStackTrace();
                return ResultMap.failure(e.getMessage());
            }

        }catch (Exception e){
            e.printStackTrace();
            return ResultMap.failure(e.getMessage());
        }

        return ResultMap.success();
    }


    public ResultMap generateAndDeploy(ModuleVo moduleVo){
        String deployPath = ResourceUtil.getResource("./").getFile() + "static/html/" + moduleVo.getModuleName();

        File dir = new File(deployPath);
        if(!dir.exists()){
            dir.mkdirs();
        }

        try {
            Map<String, StringBuffer> fileStrMap = createModuleFile(moduleVo);
            StringBuffer sqlBuffer = new StringBuffer();
            for(String tempFile : fileStrMap.keySet()){
                if(tempFile.endsWith(".html")){
                    File htmlFile = new File(deployPath + "/" + tempFile);
                    FileUtil.writeString(fileStrMap.get(tempFile).toString(), htmlFile, Charset.forName(CHAR_SET));
                }
                else if(tempFile.endsWith(".sql")){
                    sqlBuffer.append(fileStrMap.get(tempFile));
                }
            }

            try{
                for(String sql : sqlBuffer.toString().replace("\r\n", " ").split(";")){
                    System.out.println(sql);
                    jdbcTemplate.execute(sql);
                }
                sqlRestContext.reloadMapping();
            }catch (Exception e){
                e.printStackTrace();
                return ResultMap.failure(e.getMessage());
            }

        }catch (Exception e){
            e.printStackTrace();
        }

        return ResultMap.success();
    }


    public ResultMap generateReportForm(ModuleVo moduleVo){




        return ResultMap.success();
    }

}
